namespace eval gui {}

proc gui::draw_shape { cpath shapes tags } {

    upvar 0 gui::settings([winfo toplevel $cpath],scale_factor) scale

    set root [winfo toplevel $cpath]

    foreach shape $shapes {

	set layer [$shape getLayer]
        set purpose [$shape getPurpose]
        set bbox [$shape getBBox]

	$cpath create rectangle [gui::transform $bbox $scale] -width 1 \
	    -fill $::gui::settings($root,$layer,$purpose,color) \
	    -stipple $::gui::settings($root,$layer,$purpose,pattern) \
	    -outline $::gui::settings($root,$layer,$purpose,color) -tag "shape $layer $tags"

    }

}

proc gui::draw_axis { cpath } {

    upvar 0 gui::settings([winfo toplevel $cpath],scale_factor) scale

    $cpath delete axis

    $cpath create line [gui::transform "-1000000 0 1000000 0" $scale canvas] -width 1 -tag axis -arrow last -fill gray20
    $cpath create line [gui::transform "0 -1000000 0 1000000" $scale canvas] -width 1 -tag axis -arrow last -fill gray20

    return 0

}

proc gui::fill_canvas { cpath } {

    $cpath delete all

    $cpath configure -background black

    gui::draw_axis $cpath

    # Draw the bbox
    gui::draw_shape $cpath [get_boundary] "diearea"

    # Draw all the instances
    foreach inst [get_instances] {
        gui::draw_shape $cpath [$inst getBoundary] "instance"
    }
  
    # Draw all the instance pins
    foreach pin [get_pins] {
        gui::draw_shape $cpath [$pin getShapes] "pin"
    }

    # Draw all the port shapes
    foreach port [get_ports] {
        gui::draw_shape $cpath [$port getShapes] "port"
    }    

    # Draw all the metal shapes
    foreach net [get_nets] {
        gui::draw_shape $cpath [$net getShapes] "net"
        foreach via [$net getVias] {
	    gui::draw_shape $cpath [$via getShapes] "via"
	}
    }

    # Draw all the metal blockages
    gui::draw_shape $cpath [get_routing_blockages] "blockage"

    return 0;
    
}

proc gui::refresh_canvas { cpath } {

    set ::gui::settings([winfo toplevel $cpath],scale_factor) 1e0

    fill_canvas $cpath

    gui::zoom_fit $cpath

}

proc gui::get_canvas { path } {

    return "[winfo toplevel $path].display.editor.canvas.layout"

}

proc gui::set_canvas_bindings { cpath } {

    # Move the origin right
    bind $cpath <KeyPress-Right> "gui::pan $cpath left"

    # Move origin left
    bind $cpath <KeyPress-Left> "gui::pan $cpath right"

    # Move origin up
    bind $cpath <KeyPress-Up> "gui::pan $cpath up"

    # Move origin down 
    bind $cpath <KeyPress-Down> "gui::pan $cpath down"

    # Fit cell to view port
    bind $cpath <KeyPress-f> "gui::zoom_fit $cpath"

    # Fit cell to view port
    bind $cpath <KeyPress-Z> "gui::zoom_out $cpath \"%x %y\""

    # Fit cell to view port
    bind $cpath <KeyPress-R> "gui::refresh_canvas $cpath"

    # Mouse roll up to zoom in
    bind $cpath <Button-5> "gui::zoom_out $cpath \"%x %y\""

    # Mouse rool down to zoom out
    bind $cpath <Button-4> "gui::zoom_in $cpath \"%x %y\""

    return 0

}

proc gui::create_canvas { path } {

    set cp [ttk::frame $path.canvas]

    set cpysc [ttk::scrollbar $cp.yscroll -command "$cp.canvas yview" -orient vertical]
    set cpxsc [ttk::scrollbar $cp.xscroll -command "$cp.canvas xview" -orient horizontal]

    pack $cpysc -side right -fill y

    set cpc [canvas $cp.layout -relief sunken -background grey \
		 -xscrollcommand "$cpxsc set" -yscrollcommand "$cpysc set" \
		 -borderwidth 0 -width 800 -height 600]

    pack $cpc -expand 1 -fill both

    pack $cpxsc -fill x

    set_canvas_bindings $cpc

    return $cp

}
